package cn.green.core.adapt.models.field;

import cn.green.core.adapt.comps.field.set.FieldConfigSetter;
import cn.green.core.adapt.comps.field.type.OrmColumnType;
import cn.green.core.adapt.models.field.abs.AbsOrmField;
import cn.green.core.annos.column.QColumn;
import cn.green.core.annos.feature.QDeleted;
import cn.green.core.annos.feature.QParentKy;
import cn.green.core.annos.feature.QPrimary;
import cn.green.core.annos.set.*;
import cn.green.core.common.enums.field.ColumnType;
import cn.green.core.model.QTableModel;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Objects;

/**
 * @author wang.yishu
 * @version 1.0
 * @className OrmField
 * @description 字段信息
 * @date 2025/5/9 16:40
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class OrmField extends AbsOrmField {
    private ColumnType columnType;

    private int length = -1;

    private int digits = -1;

    public OrmField(Class<?> clazz, QTableModel table,Field field) {
        super(clazz, table, field);
        if (field == null) {
            throw new NullPointerException("field is null");
        }
        if (table == null) {
            throw new NullPointerException("table is null");
        }
        this.field = field;
        this.table = table;
        QColumn column = field.getAnnotation(QColumn.class);
        if (column == null) {
            return;
        }
        this.sourceName = this.table.getSourceName();
        this.schemeName = this.table.getSchemeName();
        this.tableName = this.table.getTableName();
        this.fieldName = column.name();
        this.aliasName = column.alias();
        this.uniqueCode = this.fieldName;
        this.oldFieldName = column.oldName();
        String fieldType = column.fieldType();
        boolean canSetConfig = true;
        if ("ORM_COLUMN_TYPE".equals(fieldType)) {
            ColumnType columnType = column.columnType();
            if (columnType == ColumnType.NONE) {
                throw new RuntimeException("columnType is NONE");
            }
            this.fieldType = "ORM_COLUMN_TYPE";
            this.columnType = columnType;
            this.length = column.length();
            this.digits = column.digits();
            JSONObject configObj = new JSONObject();
            configObj.put("type", columnType);
            configObj.put("length", this.length);
            configObj.put("digits", this.digits);
            this.setConfigObj(configObj);
            canSetConfig = false;
        } else {
            if (fieldType == null || fieldType.isEmpty()) {
                throw new RuntimeException("fieldType is empty");
            }
            this.fieldType = fieldType;
        }
        this.config = column.config();
        QFieldAuth auth = this.field.getAnnotation(QFieldAuth.class);
        if (auth != null) {
            this.fieldAuth = auth.auth();
        }
        QFieldForm form = this.field.getAnnotation(QFieldForm.class);
        if (form != null) {
            this.fieldForm = form.form();
        }
        QFieldCheck check = this.field.getAnnotation(QFieldCheck.class);
        if (check != null) {
            this.fieldCheck = Arrays.asList(check.checks());
        }
        QDefault qDefault = this.field.getAnnotation(QDefault.class);
        if (qDefault != null) {
            this.defaultType = qDefault.type();
            this.defaultValue = qDefault.value();
        }
        QFieldConfig qConfig = this.field.getAnnotation(QFieldConfig.class);
        if (qConfig != null && canSetConfig) {
            String configStr = qConfig.config();
            if (configStr != null && !configStr.isEmpty()) {
                this.setConfigObj(configStr);
            } else {
                Class<? extends FieldConfigSetter> setter = qConfig.setter();
                try {
                    FieldConfigSetter fieldConfigSetter = setter.newInstance();
                    this.setConfigObj(fieldConfigSetter.get());
                } catch (InstantiationException | IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        this.status = "1";
    }

    public int getLength() {
        if (this.length == -1) {
            if (this.getConfigObj() != null && Objects.equals(this.fieldType, OrmColumnType.TYPE_CODE)) {
                JSONObject config = (JSONObject) this.getConfigObj();
                return config.getIntValue("length");
            }
        }
        return this.length;
    }

    public int getDigits() {
        if (this.digits == -1) {
            if (this.getConfigObj() != null && Objects.equals(this.fieldType, OrmColumnType.TYPE_CODE)) {
                JSONObject config = (JSONObject) this.getConfigObj();
                return config.getIntValue("digits");
            }
        }
        return this.digits;
    }

    public ColumnType getColumnType() {
        if (this.columnType == null) {
            if (this.getConfigObj() != null && Objects.equals(this.fieldType, OrmColumnType.TYPE_CODE)) {
                JSONObject config = (JSONObject) this.getConfigObj();
                return ColumnType.valueOf(config.getString("type"));
            }
        }
        return this.columnType;
    }

}
